package xpn.platform.modules.security;

import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import xpn.platform.common.exception.XpnExceptionCodeEnum;
import xpn.platform.common.exception.XpnBusinessException;
import xpn.platform.modules.sys.permission.SysPermissionService;
import xpn.platform.modules.sys.user.SysUser;
import xpn.platform.modules.sys.user.SysUserDAO;

import lombok.extern.slf4j.Slf4j;

import javax.script.ScriptException;

/**
 * 用于Shiro的认证和授权
 *
 * @author duwei 2017-08-24
 */
@Slf4j
public class ShiroAuthorizingRealm extends AuthorizingRealm {

	@Autowired
	private SysUserDAO sysUserDao;

	@Autowired
	private SysPermissionService sysPermissionService;

	@Override
	public boolean supports(AuthenticationToken token) {
		return true;
	}

	/**
	 * 授权(验证权限时调用)
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		// 获取session中的用户
		SysUser user = (SysUser) principals.getPrimaryPrincipal();
		if (user == null) {
			throw new XpnBusinessException(XpnExceptionCodeEnum.USER_NOT_FOUND);
		}
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

		log.info("ShiroAuthorizingRealm : doGetAuthorizationInfo for " + user.getUserName());

		// 设置用户拥有的授权列表
		try {
			authorizationInfo.setStringPermissions(sysPermissionService.getUserPermissions(user));
		} catch (ScriptException e) {
			e.printStackTrace();
			throw new XpnBusinessException(1, e.getMessage());
		}

		return authorizationInfo;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) {
		// 查询用户信息
		UsernamePasswordToken token = (UsernamePasswordToken) authToken;
		String userName = token.getUsername();
		SysUser user = sysUserDao.findOneByUserName(userName);

		log.info("ShiroAuthorizingRealm : doGetAuthenticationInfo for " + userName);

		// 未找到用户
		if (user == null) {
			throw new XpnBusinessException(XpnExceptionCodeEnum.USER_NOT_FOUND, "User name=" + userName + "!");
		}

		// 账号被锁定
		if (!user.getEnable()) {
			throw new XpnBusinessException(XpnExceptionCodeEnum.USER_ACCOUNT_LOCKED);
		}

		return new SimpleAuthenticationInfo(user, user.getRealPassword(), getName());
	}
}
